import { fetchCapabilityDocumentation } from '@/service'
import WMTS from '@/utils/resolveWMTS'
import ExceptionLogger from '@/utils/errorHandler'
import { getCoordinateSystemProjInfo, coordinateConversion, getCoordinateSystemType, computedOpenlayersCRSDefined } from '@/utils/coordinateSystem'

export const useWMTSStore = defineStore('wmts-store', {
  state: () => {
    return {
      fetchURL: '',
      token: false,
      tokenInfo: {
        type: 'token' | 'key',
        value: ''
      },
      wmtsInfo: {},
      currentTileMatrixSet: {},
      currentLayerTitle: '',
      getCapabilitiesURL: '',
      getTileLayer: '',
      currentBboxs: [],
      leafletAddCode: '',
      openlayersAddCode: '',
      cesiumAddCode: '',
      supermap3dAddCode: ''
    }
  },
  actions: {
    async initWMTSInfo(wmtsURL) {
      this.fetchURL = wmtsURL
      // 判断有无token, 并获取token值
      const requestURL = new URL(wmtsURL)
      const queryParams = new URLSearchParams(requestURL.search)
      this.token = queryParams.has('token') || queryParams.has('key')
      if (this.token) {
        const tokenType = queryParams.has('token') ? 'token' : 'key'
        const tokenValue = queryParams.get(tokenType)
        this.tokenInfo = {
          type: tokenType,
          value: tokenValue
        }
      }
      const wmts = new WMTS(await fetchCapabilityDocumentation(this.fetchURL))
      this.wmtsInfo = wmts.info
      this.wmtsInfo.mapLayer = await wmts.resolveLayers()
      this.getCapabilitiesURL = wmtsURL
      this.getTileLayer = this.token ? `${wmts.info.getTileURL}?${this.tokenInfo.type}=${this.tokenInfo.value}` : `${wmts.info.getTileURL}`
      this.currentTileMatrixSet = this.wmtsInfo.mapLayer[0].TileMatrixSet[0]
      this.currentBboxs = this.wmtsInfo.mapLayer[0].BoundingBox
      this.currentLayerTitle = this.wmtsInfo.mapLayer[0].Title
    },

    async initWMTSInfoByFile(wmtsInfo) {
      const wmts = new WMTS(wmtsInfo)
      this.wmtsInfo = wmts.info
      this.wmtsInfo.mapLayer = await wmts.resolveLayers()
      this.getTileLayer = wmts.info.getTileURL
      this.currentTileMatrixSet = this.wmtsInfo.mapLayer[0].TileMatrixSet[0]
      this.currentBboxs = this.wmtsInfo.mapLayer[0].BoundingBox
      this.currentLayerTitle = this.wmtsInfo.mapLayer[0].Title
    },

    getTileMatrixSetBBox(SupportedCRS) {
      return this.currentBboxs.find((item) => item.crs === SupportedCRS) || null
    },

    setCurrentTileMatrixSet(tileMatrixSetName) {
      for (const item of this.wmtsInfo.mapLayer) {
        const tileMatrixSetFound = item.TileMatrixSet.find((matrix) => matrix.TileMatrixSetName === tileMatrixSetName)
        if (tileMatrixSetFound) {
          this.currentTileMatrixSet = tileMatrixSetFound
          this.currentBboxs = item.BoundingBox
          this.currentLayerTitle = item.Title
        }
      }
    },

    async setLeafletAddCode() {
      const match = JSON.stringify(this.currentTileMatrixSet.SupportedCRS).match(/EPSG:(\d+)/)
      const epsgcodeValue = match ? parseInt(match[1], 10) : null
      if (epsgcodeValue < 2000 || epsgcodeValue > 9040) {
        this.leafletAddCode = ''
        return ExceptionLogger.logException(`EPSG code为 ${epsgcodeValue}, 无法解析坐标系, 请检查数据来源是否正确!`)
      }
      const proj4Defined = await getCoordinateSystemProjInfo(epsgcodeValue)
      const bbox = this.getTileMatrixSetBBox(this.currentTileMatrixSet.SupportedCRS)
      const transformBbox =
        epsgcodeValue === 4326
          ? null
          : await coordinateConversion(
              [
                [parseFloat(bbox.minx), parseFloat(bbox.miny)],
                [parseFloat(bbox.maxx), parseFloat(bbox.maxy)]
              ],
              epsgcodeValue
            )
      const crsType = await getCoordinateSystemType(this.currentTileMatrixSet.SupportedCRS)

      switch (proj4Defined) {
        case 4326:
          this.leafletAddCode = `
window.LMap_wmts = L.map(document.getElementById('LMap_wmts'), {
  crs: new L.Proj.CRS('EPSG:4326', {
    origin: L.point(${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}),
    resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
  })
})
new L.supermap.WMTSLayer('${this.getTileLayer}', {
  layer: '${this.currentLayerTitle}',
  style: 'default',
  tilematrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
  format: 'image/png',
  requestEncoding: 'KVP'
}).addTo(LMap_wmts)
LMap_wmts.fitBounds(
  L.latLngBounds([
    [${bbox.maxy}, ${bbox.maxx}],
    [${bbox.miny}, ${bbox.minx}]
  ])
)
`
          break
        case 3857:
          this.leafletAddCode = `
window.LMap_wmts = L.map(document.getElementById('LMap_wmts'), {
  crs: new L.Proj.CRS('EPSG:3857', {
    origin: L.point(${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}),
    resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
  })
})
new L.supermap.WMTSLayer('${this.getTileLayer}', {
  layer: '${this.currentLayerTitle}',
  style: 'default',
  tilematrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
  format: 'image/png',
  requestEncoding: 'KVP'
}).addTo(LMap_wmts)
LMap_wmts.fitBounds(
  L.latLngBounds([
    [${transformBbox[0][1]}, ${transformBbox[0][0]}],
    [${transformBbox[1][1]}, ${transformBbox[1][0]}]
  ])
)
`
          break
        default:
          const originDefined = crsType === 'GEOGCS' ? `L.point(${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]})` : `L.point(${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]})`
          this.leafletAddCode = `
${proj4Defined}
window.LMap_wmts = L.map(document.getElementById('LMap_wmts'), {
  crs: new L.Proj.CRS('EPSG:${epsgcodeValue}', {
    origin: ${originDefined},
    resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
  })
})
new L.supermap.WMTSLayer('${this.getTileLayer}', {
  layer: '${this.currentLayerTitle}',
  style: 'default',
  tilematrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
  format: 'image/png',
  requestEncoding: 'KVP'
}).addTo(LMap_wmts)
LMap_wmts.fitBounds(
  L.latLngBounds([
    [${transformBbox[0][1]}, ${transformBbox[0][0]}],
    [${transformBbox[1][1]}, ${transformBbox[1][0]}]
  ])
)
`
          break
      }
    },

    async setOpenlayersAddCode() {
      const match = JSON.stringify(this.currentTileMatrixSet.SupportedCRS).match(/EPSG:(\d+)/)
      const epsgcodeValue = match ? parseInt(match[1], 10) : null
      if (epsgcodeValue < 2000 || epsgcodeValue > 9040) {
        this.openlayersAddCode = ''
        return ExceptionLogger.logException(`EPSG code为 ${epsgcodeValue}, 无法解析坐标系, 请检查数据来源是否正确!`)
      }
      const proj4Defined = await getCoordinateSystemProjInfo(epsgcodeValue)
      const bbox = this.getTileMatrixSetBBox(this.currentTileMatrixSet.SupportedCRS)
      const crsType = await getCoordinateSystemType(this.currentTileMatrixSet.SupportedCRS)

      switch (proj4Defined) {
        case 4326:
          this.openlayersAddCode = `
window.olMap_wmts = new Map({
  target: document.getElementById('olMap_wmts'),
  view: new View({
    projection: 'EPSG:4326',
    multiWorld: true
  })
})
const wmtsLayer = new TileLayer({
  source: new WMTS({
    url: '${this.getTileLayer}',
    layer: '${this.currentLayerTitle}',
    matrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
    format: 'image/png',
    tileGrid: new WMTSTileGrid({
      origin: [${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}],
      matrixIds: [${this.currentTileMatrixSet.TileMatrix.Identifier}],
      resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
    }),
    style: 'default'
  })
})
olMap_wmts.addLayer(wmtsLayer)
olMap_wmts.getView().fit([${bbox.minx}, ${bbox.miny}, ${bbox.maxx}, ${bbox.maxy}])
`
          break
        case 3857:
          this.openlayersAddCode = `
window.olMap_wmts = new Map({
  target: document.getElementById('olMap_wmts'),
  view: new View({
    projection: 'EPSG:3857',
    multiWorld: true
  })
})
const wmtsLayer = new TileLayer({
  source: new WMTS({
    url: '${this.getTileLayer}',
    layer: '${this.currentLayerTitle}',
    matrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
    format: 'image/png',
    tileGrid: new WMTSTileGrid({
      origin: [${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}],
      matrixIds: [${this.currentTileMatrixSet.TileMatrix.Identifier}],
      resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
    }),
    style: 'default'
  })
})
olMap_wmts.addLayer(wmtsLayer)
olMap_wmts.getView().fit([${bbox.minx}, ${bbox.miny}, ${bbox.maxx}, ${bbox.maxy}])
`
          break
        default:
          const crs = await computedOpenlayersCRSDefined(epsgcodeValue)
          const originDefined = crsType === 'GEOGCS' ? `[${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}]` : `[${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][1]}, ${this.currentTileMatrixSet.TileMatrix.TopLeftCorner[0][0]}]`
          this.openlayersAddCode = `
${proj4Defined}
window.olMap_wmts = new Map({
  target: document.getElementById('olMap_wmts'),
  view: new View({
    projection: ${crs},
    multiWorld: true
  })
})
const wmtsLayer = new TileLayer({
  source: new WMTS({
    url: '${this.getTileLayer}',
    layer: '${this.currentLayerTitle}',
    matrixSet: '${this.currentTileMatrixSet.TileMatrixSetName}',
    format: 'image/png',
    tileGrid: new WMTSTileGrid({
      origin: ${originDefined},
      matrixIds: [${this.currentTileMatrixSet.TileMatrix.Identifier}],
      resolutions: [${this.currentTileMatrixSet.TileMatrix.Resolution}]
    }),
    style: 'default'
  })
})
olMap_wmts.addLayer(wmtsLayer)
olMap_wmts.getView().fit([${bbox.minx}, ${bbox.miny}, ${bbox.maxx}, ${bbox.maxy}])
`
          break
      }
    },

    async setSuperMap3DAddCode() {
      const match = JSON.stringify(this.currentTileMatrixSet.SupportedCRS).match(/EPSG:(\d+)/)
      const epsgcodeValue = match ? parseInt(match[1], 10) : null
      if (epsgcodeValue < 2000 || epsgcodeValue > 9040) {
        this.supermap3dAddCode = ''
        return ExceptionLogger.logException(`EPSG code为 ${epsgcodeValue}, 无法解析坐标系, 请检查数据来源是否正确!`)
      }
      const bbox = this.getTileMatrixSetBBox(this.currentTileMatrixSet.SupportedCRS)
      const transformBbox =
        epsgcodeValue === 4326
          ? null
          : await coordinateConversion(
              [
                [parseFloat(bbox.minx), parseFloat(bbox.miny)],
                [parseFloat(bbox.maxx), parseFloat(bbox.maxy)]
              ],
              epsgcodeValue
            )
      const crsType = await getCoordinateSystemType(this.currentTileMatrixSet.SupportedCRS)
      if (this.currentTileMatrixSet.WellKnownScaleSet === 'Custom') {
        this.supermap3dAddCode = `
smViewer_wmts.imageryLayers.addImageryProvider(
  new SuperMap3D.WebMapTileServiceImageryProvider({
    url: '${this.getTileLayer}',
    format: 'image/png',
    layer: '${this.currentLayerTitle}',
    style: 'default',
    tileMatrixSetID: '${this.currentTileMatrixSet.TileMatrixSetName}',
    tilingScheme: new SuperMap3D.GeographicTilingScheme({
      customDPI: new SuperMap3D.Cartesian2(${this.currentTileMatrixSet.DPI}, ${this.currentTileMatrixSet.DPI}),
      rectangle: SuperMap3D.Rectangle.fromDegrees(${transformBbox ? transformBbox[0][0] : bbox.minx}, ${transformBbox ? transformBbox[0][1] : bbox.miny}, ${transformBbox ? transformBbox[1][0] : bbox.maxx}, ${transformBbox ? transformBbox[1][1] : bbox.maxy}),
      scaleDenominators: [${this.currentTileMatrixSet.TileMatrix.ScaleDenominator}]
    })
  })
)
smViewer_wmts.scene.camera.flyTo({
  destination: new SuperMap3D.Rectangle(SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[0][0] : bbox.minx}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[0][1] : bbox.miny}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[1][0] : bbox.maxx}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[1][1] : bbox.maxy})),
  duration: 2
})`
      } else {
        this.supermap3dAddCode = `
smViewer_wmts.imageryLayers.addImageryProvider(
  new SuperMap3D.WebMapTileServiceImageryProvider({
    url: '${this.getTileLayer}',
    format: 'image/png',
    layer: '${this.currentLayerTitle}',
    style: 'default',
    tileMatrixSetID: '${this.currentTileMatrixSet.TileMatrixSetName}',
    tilingScheme: new SuperMap3D.${crsType === 'GEOGCS' ? 'GeographicTilingScheme' : 'WebMercatorTilingScheme'}({
      customDPI: new SuperMap3D.Cartesian2(${this.currentTileMatrixSet.DPI}, ${this.currentTileMatrixSet.DPI}),
      scaleDenominators: [${this.currentTileMatrixSet.TileMatrix.ScaleDenominator}]
    })
  })
)
smViewer_wmts.scene.camera.flyTo({
  destination: new SuperMap3D.Rectangle(SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[0][0] : bbox.minx}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[0][1] : bbox.miny}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[1][0] : bbox.maxx}), SuperMap3D.Math.toRadians(${transformBbox ? transformBbox[1][1] : bbox.maxy})),
  duration: 2
})`
      }
    },

    async setCesiumAddCode() {
      const match = JSON.stringify(this.currentTileMatrixSet.SupportedCRS).match(/EPSG:(\d+)/)
      const epsgcodeValue = match ? parseInt(match[1], 10) : null
      if (epsgcodeValue < 2000 || epsgcodeValue > 9040) {
        this.cesiumAddCode = ''
        return ExceptionLogger.logException(`EPSG code为 ${epsgcodeValue}, 无法解析坐标系, 请检查数据来源是否正确!`)
      }
      const bbox = this.getTileMatrixSetBBox(this.currentTileMatrixSet.SupportedCRS)
      const transformBbox =
        epsgcodeValue === 4326
          ? null
          : await coordinateConversion(
              [
                [parseFloat(bbox.minx), parseFloat(bbox.miny)],
                [parseFloat(bbox.maxx), parseFloat(bbox.maxy)]
              ],
              epsgcodeValue
            )
      const crsType = await getCoordinateSystemType(this.currentTileMatrixSet.SupportedCRS)
      if (this.currentTileMatrixSet.WellKnownScaleSet === 'Custom') {
        this.cesiumAddCode = `
viewer_wmts.imageryLayers.addImageryProvider(
  new Cesium.WebMapTileServiceImageryProvider({
    url: '${this.getTileLayer}',
    format: 'image/png',
    layer: '${this.currentLayerTitle}',
    style: 'default',
    tileMatrixSetID: '${this.currentTileMatrixSet.TileMatrixSetName}',
    tilingScheme: new Cesium.GeographicTilingScheme({
      rectangle: Cesium.Rectangle.fromDegrees(${transformBbox ? transformBbox[0][0] : bbox.minx}, ${transformBbox ? transformBbox[0][1] : bbox.miny}, ${transformBbox ? transformBbox[1][0] : bbox.maxx}, ${transformBbox ? transformBbox[1][1] : bbox.maxy}),
    })
  })
)
viewer_wmts.scene.camera.flyTo({
  destination: new Cesium.Rectangle(Cesium.Math.toRadians(${transformBbox ? transformBbox[0][0] : bbox.minx}), Cesium.Math.toRadians(${transformBbox ? transformBbox[0][1] : bbox.miny}), Cesium.Math.toRadians(${transformBbox ? transformBbox[1][0] : bbox.maxx}), Cesium.Math.toRadians(${transformBbox ? transformBbox[1][1] : bbox.maxy})),
  duration: 0
})`
      } else {
        this.cesiumAddCode = `
viewer_wmts.imageryLayers.addImageryProvider(
  new Cesium.WebMapTileServiceImageryProvider({
    url: '${this.getTileLayer}',
    format: 'image/png',
    layer: '${this.currentLayerTitle}',
    style: 'default',
    tileMatrixSetID: '${this.currentTileMatrixSet.TileMatrixSetName}',${crsType === 'GEOGCS' ? `\n    tileMatrixLabels: [${this.currentTileMatrixSet.TileMatrix.Identifier.map((num) => num + 1)}],` : ''}
    tilingScheme: new Cesium.${crsType === 'GEOGCS' ? 'GeographicTilingScheme' : 'WebMercatorTilingScheme'}()
  })
)
viewer_wmts.scene.camera.flyTo({
  destination: new Cesium.Rectangle(Cesium.Math.toRadians(${transformBbox ? transformBbox[0][0] : bbox.minx}), Cesium.Math.toRadians(${transformBbox ? transformBbox[0][1] : bbox.miny}), Cesium.Math.toRadians(${transformBbox ? transformBbox[1][0] : bbox.maxx}), Cesium.Math.toRadians(${transformBbox ? transformBbox[1][1] : bbox.maxy})),
  duration: 0
})`
      }
    }
  }
})
